import cv2
from cvzone.HandTrackingModule import HandDetector
from cvzone.FaceMeshModule import FaceMeshDetector
from time import sleep
import numpy as np
from pynput.keyboard import Controller

import cvzone

cap = cv2.VideoCapture(0)

# 设置窗体大小
cap.set(3, 1280)
cap.set(4, 720)

# 手检测器 检测手型准确性
detector = HandDetector(detectionCon=0.7)
# 检测脸
detectorFace = FaceMeshDetector(minDetectionCon=0.9)

keys = [["Q", "W", "E"],
        ["A", "S", "D"],
        ["Z"]]

# 设置显示的文本
showText = ""

# 键盘控制器
keyborad = Controller()


# 设置通用按钮描绘方法
class Button():
    def __init__(self, pos, text, size=[85, 85]):
        self.pos = pos
        self.size = size
        self.text = text

    # def draw(self,img):
    #     # 创建一个按钮 设计基本样式
    #     x,y = self.pos
    #     w,h = self.size
    #     cv2.rectangle(img, self.pos, (x+w,y+h), (255, 310, 90), cv2.FILLED)
    #     cv2.putText(img, self.text, (x+25,y+75), cv2.FONT_HERSHEY_PLAIN, 5, (255, 255, 255), 5)
    #     return img


# 重写所有按钮生成方法
def drawAll(img, buttonList):
    for button in buttonList:
        # 创建一个按钮 设计基本样式
        x, y = button.pos
        w, h = button.size
        cv2.rectangle(img, button.pos, (x + w, y + h), (255, 310, 90), 2)
        cv2.putText(img, button.text, (x + 25, y + 75), cv2.FONT_HERSHEY_PLAIN, 5, (255, 255, 255), 5)
    return img


def drawNewAll(img, buttonList):
    # 创建一个图片蒙版
    imgNew = np.zeros_like(img, np.uint8)
    for button in buttonList:
        # 创建一个按钮 设计基本样式
        x, y = button.pos
        w, h = button.size
        # cvzone.cornerRect(img, (button.pos[0]), button.pos[1], button.size[0], button.size[1], 20)
        cv2.rectangle(imgNew, button.pos, (x + w, y + h), (255, 310, 90), cv2.FILLED)
        cv2.putText(imgNew, button.text, (x + 25, y + 75), cv2.FONT_HERSHEY_PLAIN, 5, (255, 255, 255), 5)

    out = img.copy()
    alpha = 0.5
    mask = imgNew.astype(bool)
    out[mask] = cv2.addWeighted(img, alpha, imgNew, 1 - alpha, 0)[mask]
    return img


# 绘制按钮列表
buttonList = []
for i in range(len(keys)):
    for j, key in enumerate(keys[i]):
        buttonList.append(Button([100 * j + 50, 100 * i + 50], key))

# 重复绘制
while True:
    ok, img = cap.read()
    # 描绘手的轮廓
    img = detector.findHands(img)
    # 显示手的位置
    lmList, boxInfo = detector.findPosition(img)
    # 绘制所有图案
    img = drawAll(img, buttonList)
    # 增加透明度
    # img = drawNewAll(img, buttonList)

    # 检查该列表是否又内容
    if lmList:
        for button in buttonList:
            x, y = button.pos
            w, h = button.size
            # 食指尖为8号点，中指是12点 参看 : https://google.github.io/mediapipe/solutions/hands
            # 食指的坐标点
            if x < lmList[8][0] < x + w and y < lmList[8][1] < y + h:
                # 绘制更新图形
                cv2.rectangle(img, button.pos, (x + w, y + h), (0, 0, 0), cv2.FILLED)
                cv2.putText(img, button.text, (x + 25, y + 75), cv2.FONT_HERSHEY_PLAIN, 5, (255, 255, 255), 5)
                l, _, _ = detector.findDistance(8, 12, img, draw=False)
                print(l)
                # 超出检测距离 不执行后续操作
                if l > 100:
                    print("暂停")
                    continue
                # 有效距离内进行检测
                if l < 50:
                    # 键入模拟文字
                    keyborad.press(button.text)
                    cv2.rectangle(img, button.pos, (x + w + 20, y + h + 20), (0, 255, 0),
                                  cv2.FILLED)
                    cv2.putText(img, button.text, (x + 25, y + 75), cv2.FONT_HERSHEY_PLAIN, 5, (255, 255, 255), 5)
                    showText += button.text
                    # sleep(0.1)

    if showText.__contains__("Z"):
        print("清空信息")
        showText = ""

    # 用户输出显示的文字信息
    # cv2.rectangle(img, (100, 400), (700,350), (0, 255, 255), cv2.FILLED)
    cv2.putText(img, showText, (50 + 25, 500 + 75), cv2.FONT_HERSHEY_PLAIN, 5, (100, 255, 200), 5)

    # 将视频流转换图片显示
    cv2.imshow("Image", img)
    # 输出视频转图片延迟显示时间
    cv2.waitKey(1)
